package com.ice.framework.web.redis;

import com.ice.framework.common.exception.BusinessException;
import com.ice.framework.web.config.RedisConfiguration;
import com.ice.framework.web.config.properties.RedisConfigProperties;
import com.ice.framework.web.helper.ConfigHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.time.Duration;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author wangwei
 * @Date 2021/12/20 19:39
 */
@Configuration
@AutoConfigureAfter({RedisConfiguration.class})
@ConditionalOnBean({StringRedisTemplate.class})
public class LocalRedisHelper implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    private static StringRedisTemplate redisTemplate = null;
    private static RedisConfigProperties redisConfigProperties = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        redisTemplate = (StringRedisTemplate) applicationContext.getBean(StringRedisTemplate.class);
        redisConfigProperties = (RedisConfigProperties) applicationContext.getBean(RedisConfigProperties.class);
    }

    public static String getConfigRedisPrex() {
        return redisConfigProperties.getPrex();
    }

    public static String getRedisResultKey(RedisKey key) {
        return getResultKey(key);
    }

    public static Boolean expire(RedisKey key, Duration timeout) {
        return redisTemplate.expire(getResultKey(key), timeout);
    }

    public static String get(RedisKey key) {
        return (String) redisTemplate.opsForValue().get(getResultKey(key));
    }

    public static String getAndSet(RedisKey key, String value) {
        return (String) redisTemplate.opsForValue().getAndSet(getResultKey(key), value);
    }

    public static boolean set(RedisKey key, String value) {
        if (!StringUtils.isEmpty(getResultKey(key)) && !StringUtils.isEmpty(value)) {
            redisTemplate.opsForValue().set(getResultKey(key), value);
            return true;
        } else {
            throw new BusinessException("参数key 和value 不能为空! ");
        }
    }

    public static boolean set(RedisKey key, String value, int seconds) {
        if (!StringUtils.isEmpty(getResultKey(key)) && !StringUtils.isEmpty(value)) {
            if (seconds <= 0) {
                throw new BusinessException("参数 过期时间不能少于 0 !");
            } else {
                redisTemplate.opsForValue().set(getResultKey(key), value, (long) seconds, TimeUnit.SECONDS);
                return true;
            }
        } else {
            throw new BusinessException("参数key 和value 不能为空!");
        }
    }

    public static boolean delete(RedisKey key) {
        if (StringUtils.isEmpty(getResultKey(key))) {
            throw new BusinessException("参数key  不能为空!");
        } else {
            return redisTemplate.delete(getResultKey(key));
        }
    }

    public static long getLifeTime(RedisKey key) {
        return redisTemplate.getExpire(getResultKey(key), TimeUnit.SECONDS);
    }

    public static Boolean hset(RedisKey key, String field, String value) {
        if (!StringUtils.isEmpty(getResultKey(key)) && !StringUtils.isEmpty(field)) {
            redisTemplate.opsForHash().put(getResultKey(key), field, value);
            return true;
        } else {
            throw new BusinessException("参数key 和value 不能为空!");
        }
    }

    public static String hget(RedisKey key, String field) {
        if (!StringUtils.isEmpty(getResultKey(key)) && !StringUtils.isEmpty(field)) {
            return (String) redisTemplate.opsForHash().get(getResultKey(key), field);
        } else {
            throw new BusinessException("参数key 和 field 不能为空!");
        }
    }

    public static Map<Object, Object> hgetAll(RedisKey key) {
        if (StringUtils.isEmpty(getResultKey(key))) {
            throw new BusinessException("参数key 不能为空 !");
        } else {
            return redisTemplate.opsForHash().entries(getResultKey(key));
        }
    }

    public static Long hdelete(RedisKey key, Object... field) {
        if (!StringUtils.isEmpty(getResultKey(key)) && field != null && field.length != 0) {
            return redisTemplate.opsForHash().delete(getResultKey(key), field);
        } else {
            throw new BusinessException("参数key 和  field [] 不能为空 !");
        }
    }

    public static boolean hisExists(RedisKey key, String field) {
        if (!StringUtils.isEmpty(getResultKey(key)) && !StringUtils.isEmpty(field)) {
            return redisTemplate.opsForHash().hasKey(getResultKey(key), field);
        } else {
            throw new BusinessException("参数key 和  field 不能为空 !");
        }
    }

    public static Long incr(RedisKey key) {
        if (StringUtils.isEmpty(getResultKey(key))) {
            throw new BusinessException("参数key 不能为空 !");
        } else {
            return redisTemplate.opsForValue().increment(getResultKey(key), 1L);
        }
    }

    public static Long incrBy(RedisKey key, long increment) {
        if (StringUtils.isEmpty(getResultKey(key))) {
            throw new BusinessException("参数key 不能为空 !");
        } else {
            return redisTemplate.opsForValue().increment(getResultKey(key), increment);
        }
    }

    public static Double incrBy(RedisKey key, double increment) {
        if (StringUtils.isEmpty(getResultKey(key))) {
            throw new BusinessException("参数key 不能为空 !");
        } else {
            return redisTemplate.opsForValue().increment(getResultKey(key), increment);
        }
    }

    public static Long hincrBy(RedisKey key, String field, long increment) {
        if (!StringUtils.isEmpty(getResultKey(key)) && !StringUtils.isEmpty(field)) {
            return redisTemplate.opsForHash().increment(getResultKey(key), field, increment);
        } else {
            throw new BusinessException("参数key 和  field 不能为空 !");
        }
    }

    public static boolean hasKey(RedisKey key) {
        Boolean result = redisTemplate.hasKey(getResultKey(key));
        return result == null ? false : result;
    }

    public static boolean setIfAbsent(RedisKey key, String value, Duration timeout) {
        Boolean result = redisTemplate.opsForValue().setIfAbsent(getResultKey(key), value, timeout);
        return result == null ? false : result;
    }

    public static String getResultKey(RedisKey key) {
        StringBuilder sb = new StringBuilder();
        String prex = key.getPrex();
        if (prex == null) {
            prex = redisConfigProperties.getPrex();
        }

        if (prex == null) {
            prex = ConfigHelper.getApplicationName() + ":";
        }

        if (!prex.endsWith(":")) {
            prex = prex + ":";
        }

        sb.append(prex);
        sb.append(key.getCode());
        String[] params = key.getParams();
        if (params != null && params.length != 0) {
            for (int i = 0; i < params.length; ++i) {
                sb.append(":").append(params[i]);
            }

            return sb.toString();
        } else {
            return sb.toString();
        }
    }
}
